package com.jie.user.service;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jie.common.constant.NumConst;
import com.jie.common.constant.RedisKey;
import com.jie.common.util.TokenUtil;
import com.jie.component.exception.base.BusinessException;
import com.jie.component.exception.enums.BusinessError;
import com.jie.model.dto.user.UserLoginWithPhoneDTO;
import com.jie.model.po.user.User;
import com.jie.model.po.user.UserPhone;
import com.jie.model.redis.user.UserRedis;
import com.jie.model.vo.user.UserLoginWitPhoneVO;
import com.jie.user.mapper.UserMapper;
import com.jie.user.mapper.UserPhoneMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @author jie
 * @version 1.0 2025-02-14
 */
@Service
@RequiredArgsConstructor
public class UserLoginService {

    private final StringRedisTemplate stringRedisTemplate;

    private final UserMapper userMapper;

    private final UserPhoneMapper userPhoneMapper;

    /**
     * 手机号登录
     * @param userLoginWithPhoneDTO
     * @return
     */
    public UserLoginWitPhoneVO loginWithPhone(UserLoginWithPhoneDTO userLoginWithPhoneDTO) {
        // 检查输入错误的次数
        String phone = userLoginWithPhoneDTO.getPhone();
        String password = userLoginWithPhoneDTO.getPassword();

        String errorKey = RedisKey.getRedisKey(RedisKey.USER_LOGIN_ERROR_COUNT + phone);
        String errorCount = stringRedisTemplate.opsForValue().get(errorKey);

        // 输入错误次数超过5次就等待
        if (StrUtil.isNotBlank(errorCount) && Integer.parseInt(errorCount) > 5) {
            throw new BusinessException(BusinessError.PHONE_ERROR_TOO_MANY);
        }

        // 从数据库中查询
        LambdaQueryWrapper<UserPhone> userPhoneQueryWrapper = new LambdaQueryWrapper<>();
        userPhoneQueryWrapper.eq(UserPhone::getPhone, phone);
        UserPhone userPhone = userPhoneMapper.selectOne(userPhoneQueryWrapper);

        if (userPhone == null) {
            // 手机号不存在，错误值 + 1
            stringRedisTemplate.opsForValue().increment(errorKey, 1);
            stringRedisTemplate.opsForValue().getAndExpire(errorKey, 1, TimeUnit.MINUTES);
            throw new BusinessException(BusinessError.PHONE_NOT_REGISTER);
        }

        if (!userPhone.getStatus().equals(NumConst.ENABLE)) {
            throw new BusinessException(BusinessError.ACCOUNT_DISABLED);
        }

        // 检查密码是否正确
        User user = userMapper.selectById(userPhone.getUserId());

        if (!password.equals(user.getPassword())) {
            // 密码错误，错误值 + 1
            stringRedisTemplate.opsForValue().increment(errorKey, 1);
            stringRedisTemplate.opsForValue().getAndExpire(errorKey, 1, TimeUnit.MINUTES);
            throw new BusinessException(BusinessError.PASSWORD_ERROR);
        }

        // 生成token
        String token = TokenUtil.generateToken(user.getId());

        // 把用户信息保存到redis中并设置登录过期的时间
        String loginUserKey = RedisKey.getRedisKey(RedisKey.LOGIN_USER_INFO + user.getId());
        UserRedis userRedis = UserRedis
                .builder()
                .id(user.getId())
                .name(user.getName())
                .phone(user.getPhone())
                .token(token)
                .build();
        stringRedisTemplate.opsForValue().set(loginUserKey, JSONUtil.toJsonStr(userRedis), 24, TimeUnit.HOURS);

        return UserLoginWitPhoneVO
                .builder()
                .token(token)
                .build();
    }
}
